From 6ad2b9b28d4f6d206ba877bfccad10b423a684ba Mon Sep 17 00:00:00 2001 From: Ashe Connor Date: Thu, 19 Oct 2017 16:15:16 +1100 Subject: [PATCH] Try current_exe, then argv0 canonicalize, then PATH --- src/cargo/util/config.rs | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 039993567..4f523ed07 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -153,10 +153,42 @@ impl Config { /// Get the path to the `cargo` executable pub fn cargo_exe(&self) -> CargoResult<&Path> { - self.cargo_exe.get_or_try_init(|| - env::current_exe().and_then(|path| path.canonicalize()) - .chain_err(|| "couldn't get the path to cargo executable") - ).map(AsRef::as_ref) + self.cargo_exe.get_or_try_init(|| { + fn from_current_exe() -> CargoResult { + env::current_exe() + .and_then(|path| path.canonicalize()) + .map_err(CargoError::from) + } + + fn from_argv() -> CargoResult { + env::args_os() + .next() + .ok_or(CargoError::from("no argv[0]")) + .map(PathBuf::from) + .and_then(|argv0| argv0.canonicalize().or_else(|_| probe_path(argv0))) + } + + fn probe_path(argv0: PathBuf) -> CargoResult { + // canonicalize failed, probe PATH if no dir sep in argv0 + if argv0.components().count() > 1 { + return Err(CargoError::from("no cargo executable candidate found")); + } + + let paths = env::var_os("PATH").ok_or(CargoError::from("no PATH"))?; + for path in env::split_paths(&paths) { + let candidate = PathBuf::from(path).join(&argv0); + if candidate.is_file() { + return candidate.canonicalize().map_err(CargoError::from); + } + } + + Err(CargoError::from("no cargo executable candidate found in PATH")) + } + + from_current_exe() + .or_else(|_| from_argv()) + .chain_err(|| "couldn't get the path to cargo executable") + }).map(AsRef::as_ref) } pub fn values(&self) -> CargoResult<&HashMap> { -- 2.30.2